package co.edu.javeriana.monopoly.server.modelo;

import java.io.IOException;

import java.io.Serializable;

import java.lang.reflect.Constructor;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;

public class Tablero  implements Serializable{
    public Tablero() throws MonopolyException {  
        try{
            inicializar();
            jugadores = new Hashtable<Integer,Jugador>();
        }catch (Exception e) {
            e.printStackTrace();
            throw new MonopolyException("Error a l iniciar los parametros de juego",e);
        }
    }
    public final int POSICIONES = 40;
    private int maxnumgrupos;
    private int maxnumpropiedades;
    private int maxnumservicios;
    private int maxnumtransportes;
    private int maxnumarcacomunal;
    private int maxnumcasualidad;
    private int pagosalida;
    
    private int actualarca=1;
    private int actualcasualidad=1;
    
    private Hashtable<Integer,Casilla> casillas;
    private Hashtable<Integer,Jugador> jugadores;
    private Hashtable<Integer,Grupo> grupos;
    private List<Casualidad> cartasCasualidad;
    private List<ArcaComunal> cartasArcaComunal;


    public void setCartasCasualidad(List<Casualidad> cartasCasualidad) {
        this.cartasCasualidad = cartasCasualidad;
    }

    public List<Casualidad> getCartasCasualidad() {
        return cartasCasualidad;
    }

    public void setCartasArcaComunal(List<ArcaComunal> cartasArcaComunal) {
        this.cartasArcaComunal = cartasArcaComunal;
    }

    public List<ArcaComunal> getCartasArcaComunal() {
        return cartasArcaComunal;
    }
    
    public Properties loadParams(String file)
        throws IOException {

      // Loads a ResourceBundle and creates Properties from it
      Properties     prop   = new Properties();
      
      ResourceBundle bundle = ResourceBundle.getBundle(file, Locale.getDefault());

      // Retrieve the keys and populate the properties object
      Enumeration enume = bundle.getKeys();
      String      key  = null;
      while (enume.hasMoreElements()) {
        key = (String) enume.nextElement();

        prop.put(key, bundle.getObject(key));
      }

      return prop;
    }

    public void loadPropertiesTablero() throws Exception{
        
        Properties conprops = null;

        try{
            conprops = loadParams("Tablero");
            maxnumgrupos = Integer.parseInt(conprops.getProperty("tablero.numerogrupos"));
            maxnumpropiedades = Integer.parseInt(conprops.getProperty("tablero.numeropropiedades"));
            maxnumservicios = Integer.parseInt(conprops.getProperty("tablero.numeroservicios"));
            maxnumtransportes = Integer.parseInt(conprops.getProperty("tablero.numerotransportes"));
            maxnumarcacomunal = Integer.parseInt(conprops.getProperty("tablero.numeroarcacomunal"));
            maxnumcasualidad = Integer.parseInt(conprops.getProperty("tablero.numerocasualidad"));
            pagosalida = Integer.parseInt(conprops.getProperty("tablero.salida"));

        }catch (Exception ex) {
          ex.printStackTrace();
          throw ex;
        } finally {
          // Clear properties
          conprops.clear();
          conprops = null;
        }

    }
    public void loadPropertiesPropiedades() throws Exception{
        
        Properties conprops = null;

        try{
            conprops = loadParams("Propiedades");
            String nombregrupos = conprops.getProperty("propiedades.nombregrupos");
            String nombrepropiedades = conprops.getProperty("propiedades.nombrepropiedades");
            String idpropiedades = conprops.getProperty("propiedades.idpropiedades");
            String valorpropiedades = conprops.getProperty("propiedades.valorpropiedades");
            String arriendo = conprops.getProperty("propiedades.arriendo");
            String valoredificaciones = conprops.getProperty("propiedades.valoredificaciones");
            String valorhipoteca = conprops.getProperty("propiedades.valorhipoteca");
            String arriendogrupo = conprops.getProperty("propiedades.arriendogrupo");
            String arriendocasa1 = conprops.getProperty("propiedades.arriendocasa1");
            String arriendocasa2 = conprops.getProperty("propiedades.arriendocasa2");
            String arriendocasa3 = conprops.getProperty("propiedades.arriendocasa3");
            String arriendocasa4 = conprops.getProperty("propiedades.arriendocasa4");
            String edificio = conprops.getProperty("propiedades.edificio");
            String grupospropiedades = conprops.getProperty("propiedades.grupospropiedades");
            
            grupos = new Hashtable<Integer,Grupo>();
            
            String[] nombregrupos_spl = nombregrupos.split(",");
            
            for (int i = 0; i < nombregrupos_spl.length; i++)  {
                Grupo g = new Grupo();
                g.setId(i+1);
                g.setName(nombregrupos_spl[i]);
                grupos.put(new Integer(g.getId()),g);
            }
            

            String[] nombrepropiedades_spl = nombrepropiedades.split(",");
            String[] valorpropiedades_spl = valorpropiedades.split(",");
            String[] idpropiedades_spl = idpropiedades.split(",");
            String[] arriendo_spl = arriendo.split(",");
            int ivaloredificaciones = Integer.parseInt(valoredificaciones);
            int ivalorhipoteca = Integer.parseInt(valorhipoteca);
            String[] arriendogrupo_spl = arriendogrupo.split(",");
            String[] arriendocasa1_spl = arriendocasa1.split(",");
            String[] arriendocasa2_spl = arriendocasa2.split(",");
            String[] arriendocasa3_spl = arriendocasa3.split(",");
            String[] arriendocasa4_spl= arriendocasa4.split(",");
            String[] edificio_spl = edificio.split(",");
            String[] grupospropiedades_spl = grupospropiedades.split(",");
            
            
            for (int i = 0; i < maxnumpropiedades; i++)  {
                Terreno t = new Terreno();
                t.setAlquiler1casa(Integer.parseInt(arriendocasa1_spl[i]));
                t.setAlquiler2casas(Integer.parseInt(arriendocasa2_spl[i]));
                t.setAlquiler3casas(Integer.parseInt(arriendocasa3_spl[i]));
                t.setAlquiler4casas(Integer.parseInt(arriendocasa4_spl[i]));
                t.setAlquilerEdificio(Integer.parseInt(edificio_spl[i]));
                t.setId(Integer.parseInt(idpropiedades_spl[i]));
                t.setNombre(nombrepropiedades_spl[i]);
                t.setPosicion(Integer.parseInt(idpropiedades_spl[i]));
                t.setPrecio(Integer.parseInt(valorpropiedades_spl[i]));
                t.setPropietario(null);
                t.setValorAlquiler(Integer.parseInt(arriendo_spl[i]));
                
                t.setValor1casa(t.getPrecio()*ivaloredificaciones/100);
                t.setValor2casas(t.getValor1casa()*ivaloredificaciones/100);
                t.setValor3casas(t.getValor2casas()*ivaloredificaciones/100);
                t.setValor4casas(t.getValor3casas()*ivaloredificaciones/100);
                t.setValorEdificio(t.getValor4casas()*ivaloredificaciones/100);
                t.setValorAlquilerGrupo(Integer.parseInt(arriendogrupo_spl[i]));
                t.setValorHipoteca(t.getPrecio()*ivalorhipoteca/100);
                
                
                casillas.put(new Integer(t.getId()),t);
            }
            
            for (int i = 0; i < maxnumpropiedades; i++)  {
                String[] grp_props = grupospropiedades_spl[i].split(":");
                Grupo g = grupos.get(Integer.valueOf(grp_props[0]));
                Propiedad p = (Propiedad)casillas.get(Integer.valueOf(grp_props[1]));
                p.setGrupo(g);
                g.getPropiedades().add(p);
            }
            
            
            
        }catch (Exception ex) {
          ex.printStackTrace();
          throw ex;
        } finally {
          // Clear properties
          conprops.clear();
          conprops = null;
        }

    }

    public void loadPropertiesServicios() throws Exception{
        
        Properties conprops = null;

        try{
            conprops = loadParams("Servicios");
            String nombres = conprops.getProperty("servicio.nombres");
            String valores = conprops.getProperty("servicio.valores");
            String ids = conprops.getProperty("servicio.id");
            String arriendo= conprops.getProperty("servicio.arriendo");
            String arriendo2= conprops.getProperty("servicio.arriendo2");
            String arriendo3= conprops.getProperty("servicio.arriendo3");
            String arriendo4= conprops.getProperty("servicio.arriendo4");
            
            
            String[] nombres_spl = nombres.split(",");
            String[] valores_spl = valores.split(",");
            String[] arriendo_spl= arriendo.split(",");
            String[] arriendo2_spl= arriendo2.split(",");
            String[] arriendo3_spl= arriendo3.split(",");
            String[] arriendo4_spl= arriendo4.split(",");
            String[] ids_spl = ids.split(",");
            int ivalorhipoteca = Integer.parseInt(conprops.getProperty("servicio.hipoteca"));
            
            
            for (int i = 0; i < maxnumservicios; i++)  {
                Servicio s = new Servicio();
                s.setId(Integer.parseInt(ids_spl[i]));
                s.setNombre(nombres_spl[i]);
                s.setPosicion(Integer.parseInt(ids_spl[i]));
                s.setPrecio(Integer.parseInt(valores_spl[i]));
                s.setValorAlquiler(Integer.parseInt(arriendo_spl[i]));
                s.setValorAlquiler(Integer.parseInt(arriendo_spl[i]));
                s.setAlquiler2servicios(Integer.parseInt(arriendo2_spl[i]));
                s.setAlquiler3servicios(Integer.parseInt(arriendo3_spl[i]));
                s.setAlquiler4servicios(Integer.parseInt(arriendo4_spl[i]));
                s.setValorHipoteca(s.getPrecio()*ivalorhipoteca/100);
                
                
                casillas.put(new Integer(s.getId()),s);
            }
            
            
        }catch (Exception ex) {
          ex.printStackTrace();
          throw ex;
        } finally {
          // Clear properties
          conprops.clear();
          conprops = null;
        }

    }

    public void loadPropertiesTransportes() throws Exception{
        
        Properties conprops = null;

        try{
            conprops = loadParams("Transporte");
            String nombres = conprops.getProperty("transporte.nombres");
            String valores = conprops.getProperty("transporte.valores");
            String ids = conprops.getProperty("transporte.id");
            String arriendo= conprops.getProperty("transporte.arriendo");
            String arriendo2= conprops.getProperty("transporte.arriendo2");
            String arriendo3= conprops.getProperty("transporte.arriendo3");
            String arriendo4= conprops.getProperty("transporte.arriendo4");
            
            
            String[] nombres_spl = nombres.split(",");
            String[] valores_spl = valores.split(",");
            String[] arriendo_spl= arriendo.split(",");
            String[] arriendo2_spl= arriendo2.split(",");
            String[] arriendo3_spl= arriendo3.split(",");
            String[] arriendo4_spl= arriendo4.split(",");
            String[] ids_spl = ids.split(",");
            int ivalorhipoteca = Integer.parseInt(conprops.getProperty("transporte.hipoteca"));
            
            
            for (int i = 0; i < maxnumtransportes; i++)  {
                Transporte t = new Transporte();
                t.setId(Integer.parseInt(ids_spl[i]));
                t.setNombre(nombres_spl[i]);
                t.setPosicion(Integer.parseInt(ids_spl[i]));
                t.setPrecio(Integer.parseInt(valores_spl[i]));
                t.setValorAlquiler(Integer.parseInt(arriendo_spl[i]));
                t.setValorAlquiler(Integer.parseInt(arriendo_spl[i]));
                t.setAlquiler2servicios(Integer.parseInt(arriendo2_spl[i]));
                t.setAlquiler3servicios(Integer.parseInt(arriendo3_spl[i]));
                t.setAlquiler4servicios(Integer.parseInt(arriendo4_spl[i]));
                t.setValorHipoteca(t.getPrecio()*ivalorhipoteca/100);
                
                
                casillas.put(new Integer(t.getId()),t);
            }
            
            
        }catch (Exception ex) {
          ex.printStackTrace();
          throw ex;
        } finally {
          // Clear properties
          conprops.clear();
          conprops = null;
        }

    }
    
    public void loadPropertiesCartas() throws Exception{
        
        Properties conprops = null;

        try{
            conprops = loadParams("Cartas");
            String[] valoresarca = conprops.getProperty("arcacomunal.valores").split(",");
            String[] valorescasualidad = conprops.getProperty("casualidad.valores").split(",");
            String[] idsarcacomunal = conprops.getProperty("arcacomunal.id").split(",");
            String[] idscasualidad= conprops.getProperty("casualidad.id").split(",");
            String[] reglascasualidad= conprops.getProperty("casualidad.regla").split(",");
            String[] reglasarca= conprops.getProperty("arcacomunal.reglas").split(",");
            
            cartasArcaComunal = new ArrayList();
            
            for (int i = 0; i < valoresarca.length; i++)  {
                ArcaComunal a = new ArcaComunal();
                a.setId(Integer.parseInt(idsarcacomunal[i]));
                a.setPosicion(Integer.parseInt(idsarcacomunal[i]));
                a.setMensaje(valoresarca[i]);
                String[] reglasarca_spl = reglasarca[i].split(":");
                
                Class cls = Class.forName("co.edu.javeriana.monopoly.server.eventos."+reglasarca_spl[0]);
                Constructor[] ct = cls.getConstructors();
                Object arglist[] = new Object[1];
                arglist[0] = new Object[]{Integer.valueOf(reglasarca_spl[1])};
                Object retobj = ct[0].newInstance(arglist);
                a.setRegla((Evento)retobj);
                cartasArcaComunal.add(a);
            }
            
            for (int i = 0; i < maxnumarcacomunal; i++)  {
                ArcaComunal a = new ArcaComunal();
                a.setId(Integer.parseInt(idsarcacomunal[i]));
                a.setPosicion(Integer.parseInt(idsarcacomunal[i]));
                casillas.put(new Integer(a.getId()),a);
            }

            cartasCasualidad = new ArrayList();
            
            for (int i = 0; i < valorescasualidad.length; i++)  {
                Casualidad c = new Casualidad();
                c.setId(Integer.parseInt(idscasualidad[i]));
                c.setPosicion(Integer.parseInt(idscasualidad[i]));
                c.setMensaje(valorescasualidad[i]);
                String[] reglascasualidad_spl = reglascasualidad[i].split(":");
                
                Class cls = Class.forName("co.edu.javeriana.monopoly.server.eventos."+reglascasualidad_spl[0]);
                Constructor[] ct = cls.getConstructors();
                Object arglist[] = new Object[1];
                arglist[0] = new Object[]{Integer.valueOf(reglascasualidad_spl[1])};
                Object retobj = ct[0].newInstance(arglist);
                
                c.setRegla((Evento)retobj);
                
                cartasCasualidad.add(c);
            }
            
            for (int i = 0; i < maxnumarcacomunal; i++)  {
                Casualidad c = new Casualidad();
                c.setId(Integer.parseInt(idscasualidad[i]));
                c.setPosicion(Integer.parseInt(idscasualidad[i]));
                casillas.put(new Integer(c.getId()),c);
            }
            
        }catch (Exception ex) {
          ex.printStackTrace();
          throw ex;
        } finally {
          // Clear properties
          conprops.clear();
          conprops = null;
        }

    }
    private void inicializar() throws MonopolyException{
        casillas = new Hashtable<Integer,Casilla>();
        try {
            loadPropertiesTablero();
            loadPropertiesPropiedades();
            loadPropertiesServicios();
            loadPropertiesTransportes();
            loadPropertiesCartas();
            Salida s = new Salida();
            s.setPosicion(1);
            s.setId(1);
            casillas.put(new Integer(s.getId()),s);
            Carcel c = new Carcel();
            c.setPosicion(11);
            c.setId(11);
            casillas.put(new Integer(c.getId()),c);
            ParadaLibre pl = new ParadaLibre();
            pl.setPosicion(21);
            pl.setId(21);
            casillas.put(new Integer(pl.getId()),pl);
            IrCarcel ic = new IrCarcel();
            ic.setPosicion(31);
            ic.setId(31);
            casillas.put(new Integer(ic.getId()),ic);
            
        } catch (Exception e) {
            throw new MonopolyException("Error al cargar las propiedades del tablero",e);
        }
        

    }
    public void setCasillas(Hashtable casillas) {
        this.casillas = casillas;
    }

    public Hashtable getCasillas() {
        return casillas;
    }

    public void setJugadores(Hashtable jugadores) {
        this.jugadores = jugadores;
    }

    public Hashtable getJugadores() {
        return jugadores;
    }

    public void setGrupos(Hashtable grupos) {
        this.grupos = grupos;
    }

    public Hashtable getGrupos() {
        return grupos;
    }

    public int getMaxnumgrupos() {
        return maxnumgrupos;
    }

    public int getMaxnumpropiedades() {
        return maxnumpropiedades;
    }

    public int getMaxnumservicios() {
        return maxnumservicios;
    }

    public int getMaxnumtransportes() {
        return maxnumtransportes;
    }

    public int getMaxnumarcacomunal() {
        return maxnumarcacomunal;
    }

    public int getPagosalida() {
        return pagosalida;
    }
    
    public Cartas traerCasualidad(){
        Cartas c = this.getCartasCasualidad().get(actualcasualidad);
        actualcasualidad++;
        if (actualcasualidad > maxnumcasualidad){
            actualcasualidad = 1;
        }
        return c;
        
    }
    public Cartas traerArcaComunal(){
        Cartas c = this.getCartasArcaComunal().get(actualarca);
        actualarca++;
        if (actualarca > maxnumarcacomunal){
            actualarca = 1;
        }
        return c;
        
    }

}
